#include "reg51.h"
#include "intrins.h"

sfr P_SW2 = 0xba;

#define I2CCFG (*(unsigned char volatile xdata *)0xfe80)
#define I2CMSCR (*(unsigned char volatile xdata *)0xfe81)
#define I2CMSST (*(unsigned char volatile xdata *)0xfe82)
#define I2CSLCR (*(unsigned char volatile xdata *)0xfe83)
#define I2CSLST (*(unsigned char volatile xdata *)0xfe84)
#define I2CSLADR (*(unsigned char volatile xdata *)0xfe85)
#define I2CTXD (*(unsigned char volatile xdata *)0xfe86)
#define I2CRXD (*(unsigned char volatile xdata *)0xfe87)

sbit SDA = P3 ^ 6;
sbit SCL = P3 ^ 7;
char ADDR = 0x4E; // PCF8574  T  模块的地址码
void Wait()
{
    while (!(I2CMSST & 0x40))
        ;
    I2CMSST &= ~0x40;
}

void Start()
{
    I2CMSCR = 0x01; //发送START命令
    Wait();
}

void SendData(char dat)
{
    I2CTXD = dat;   //写数据到数据缓冲区
    I2CMSCR = 0x02; //发送SEND命令
    Wait();
}

void RecvACK()
{
    I2CMSCR = 0x03; //发送读ACK命令
    Wait();
}

char RecvData()
{
    I2CMSCR = 0x04; //发送RECV命令
    Wait();
    return I2CRXD;
}

void SendACK()
{
    I2CMSST = 0x00; //设置ACK信号
    I2CMSCR = 0x05; //发送ACK命令
    Wait();
}

void SendNAK()
{
    I2CMSST = 0x01; //设置NAK信号
    I2CMSCR = 0x05; //发送ACK命令
    Wait();
}

void Stop()
{
    I2CMSCR = 0x06; //发送STOP命令
    Wait();
}

void Delay()
{
    int i;

    for (i = 0; i < 3000; i++)
    {
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    }
}
void init()
{
}
void main()
{
    P_SW2 = 0x80;

    I2CCFG = 0xe0; //使能I2C主机模式
    I2CMSST = 0x00;

    Start();        //发送起始命令
    SendData(0xa2); //发送设备地址+写命令
    RecvACK();
    SendData(0x02); //发送存储地址
    RecvACK();
    SendData(0x00); //设置秒值
    RecvACK();
    SendData(0x00); //设置分钟值
    RecvACK();
    SendData(0x12); //设置小时值
    RecvACK();
    Stop(); //发送停止命令

    while (1)
    {
        Start();        //发送起始命令
        SendData(0xa2); //发送设备地址+写命令
        RecvACK();
        SendData(0x02); //发送存储地址
        RecvACK();
        Start();        //发送起始命令
        SendData(0xa3); //发送设备地址+读命令
        RecvACK();
        P0 = RecvData(); //读取秒值
        SendACK();
        P2 = RecvData(); //读取分钟值
        SendACK();
        P3 = RecvData(); //读取小时值
        SendNAK();
        Stop(); //发送停止命令

        Delay();
    }
}
